#include "WorkerThread.h"
#include "ThreadPool.h"
#include "Runtime/Debug/Logger.h"
namespace BattleFire{
	int32 GRenderThreadPollPeriodMs = -1;
	std::atomic<ENamedThreads> RenderThreadStatics::RenderThread;
	std::atomic<ENamedThreads> RenderThreadStatics::RenderThread_Local;
	int32 bHasBackgroundThreads = CREATE_BACKGROUND_TASK_THREADS;
	int32 bHasHighPriorityThreads = CREATE_HIPRI_TASK_THREADS;
	uint32 WorkerThread::TlsSlot = WorkerThread::GetTlsSlot();
	uint32 WorkerThread::RenderThreadID=0;
	uint32 WorkerThread::GameThreadID=0;
	WorkerThread::WorkerThread(const char *inName)
	{
		memset(mThreadName,0,64);
		strcpy(mThreadName,inName);
		mThreadInitSyncEvent=nullptr;
	}
	WorkerThread::~WorkerThread()
	{
		Kill(true);
	}

	void WorkerThread::SetTls()
	{
		FPlatformTLS::SetTlsValue( TlsSlot, this );
	}
	void WorkerThread::FreeTls()
	{
		FPlatformTLS::SetTlsValue( TlsSlot, nullptr );
	}
	bool WorkerThread::Kill(bool bShouldWait)
	{
		bool bDidExitOK = true;
		if (mThreadBody)
		{
			mThreadBody->Stop();
		}
		if (bShouldWait == true)
		{
			mThread->join();
		}
		mThread = NULL;
		return bDidExitOK;
	}
	void WorkerThread::WaitForCompletion()
	{
		mThread->join();
	}
	
	uint32 WorkerThread::GetTlsSlot()
	{
		uint32 TlsSlot = FPlatformTLS::AllocTlsSlot();
		return TlsSlot;
	}

	WorkerThread* WorkerThread::Create(const char * inName,ThreadBody* inThreadBody)
	{
		WorkerThread*thread=new WorkerThread(inName);
		thread->CreateInternal(inThreadBody);
		thread->PostCreate();
		return thread;
	}
	bool WorkerThread::CreateInternal(ThreadBody* inThreadBody)
	{
		mThreadBody = inThreadBody;
		mThreadInitSyncEvent	= new BattleFireEvent;
		mThread = new std::thread(&WorkerThread::Entry,this);
		if (mThread == nullptr)
		{
			mThreadBody = nullptr;
		}
		else
		{
			mThreadInitSyncEvent->Wait(INFINITE);
		}
		delete mThreadInitSyncEvent;
		return true;
	}
	void WorkerThread::Entry()
	{
		mThreadID=mThread->get_id();
		PlatformMisc::SetThreadName(mThreadName);
		if (mThreadBody->Init() == true)
		{
			mThreadInitSyncEvent->TriggerAll();
			SetTls();
			mThreadBody->Run();
			mThreadBody->Exit();
			FreeTls();
		}
		else
		{
			mThreadInitSyncEvent->TriggerAll();
		}
	}

}
